using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using System.Text.Json;
using WalkingTec.Mvvm.Core;
using UUIDNext;
using HengTong.Model.Db.Hr.Attendance;
using TiaoTaoHelper.Extension.String;


namespace HengTong.ViewModel.Hr.SysAttendanceShiftGroupVms
{
    public partial class SysAttendanceShiftGroupVm : CrudVm<SysAttendanceShiftGroup>
    {
        /// <summary>
        /// 班次选项
        /// </summary>
        public Dictionary<ShiftGroupType, List<string>> ShiftItems { get; set; }

        /// <summary>
        /// 获取或设置班倒班次的工作日期
        /// </summary>
        public DateOnly? WorkDate { get; set; }

        /// <summary>
        /// 班次
        /// </summary>
        public string ShiftTag { get; set; }

        /// <summary>
        /// 行政班的工作日配置
        /// </summary>
        public List<string> WorkDays { get; set; } = new();

        /// <summary>
        /// 两班倒或三班倒的简单排班结果
        /// key: 日期
        /// value: 班次名称
        /// </summary>
        public Dictionary<DateOnly, string> SimpleSchedule { get; set; } = new();

        public SysAttendanceShiftGroupVm()
        {
            SetInclude(x => x.Shifts);
        }

        protected override void InitVM()
        {
            SelectedShiftsIds = Entity.Shifts?.Select(x => x.ShiftId.ToString()).ToList();
            // 回显班次标签映射
            ShiftTagMapping = Entity.Shifts?
                .Where(x => x.ShiftId.HasValue && x.Tag.HasValue)
                .ToDictionary(
                    x => x.ShiftId.ToString(),
                    x => x.Tag.Value
                ) ?? new Dictionary<string, SysAttendanceShiftTag>();
            ShiftItems = new Dictionary<ShiftGroupType, List<string>>
            {
                { ShiftGroupType.三班倒, ["A", "B", "休"] },
                { ShiftGroupType.两班倒, ["班", "休"] },
                { ShiftGroupType.上一休二, ["班", "休1", "休2"] },
                { ShiftGroupType.行政班, ["星期一", "星期二", "星期三", "星期四", "星期五", "星期六", "星期天"] }
            };
            if (Entity?.Type == ShiftGroupType.行政班 && !string.IsNullOrWhiteSpace(Entity.SchedulePattern) &&
                Entity.SchedulePattern.TryJsonParse(out List<string> days))
            {
                WorkDays = days;
            }
            else if ((Entity?.Type == ShiftGroupType.三班倒 || Entity?.Type == ShiftGroupType.两班倒 ||
                      Entity?.Type == ShiftGroupType.上一休二) &&
                     !string.IsNullOrWhiteSpace(Entity.SchedulePattern) &&
                     Entity.SchedulePattern.TryJsonParse(out ShiftGroupDayInfo info))
            {
                if (info.WorkDate != null)
                {
                    if (Entity.Type == ShiftGroupType.三班倒)
                    {
                        WorkDate = info.WorkDate;
                        ShiftTag = info.ShiftTag;
                        {
                            var m = Math.Abs((DateTime.Today - info.WorkDate.Value.ToDateTime(TimeOnly.MinValue)).Days %
                                             3);
                            if (m == 0)
                            {
                                WorkDate = DateOnly.FromDateTime(DateTime.Today);
                            }
                            else if (m == 1)
                            {
                                WorkDate = DateOnly.FromDateTime(DateTime.Today);
                                ShiftTag = "B";
                            }
                            else if (m == 2)
                            {
                                WorkDate = DateOnly.FromDateTime(DateTime.Today);
                                ShiftTag = "休";
                            }
                            else
                            {
                                throw new Exception("计算班次错误");
                            }
                        }
                        var monthStart = new DateTime(DateTime.Now.Year, info.WorkDate.Value.Month, 1);
                        var monthDays = DateTime.DaysInMonth(DateTime.Now.Year, DateTime.Now.Month);
                        for (int i = 0; i < monthDays; i++)
                        {
                            var dayCount = (monthStart - info.WorkDate.Value.ToDateTime(TimeOnly.MinValue)).Days;
                            var mod = Math.Abs(dayCount % 3);
                            if (mod == 0)
                            {
                                SimpleSchedule.Add(DateOnly.FromDateTime(monthStart), "A");
                            }
                            else if (mod == 1)
                            {
                                SimpleSchedule.Add(DateOnly.FromDateTime(monthStart), "B");
                            }
                            else if (mod == 2)
                            {
                                SimpleSchedule.Add(DateOnly.FromDateTime(monthStart), "休");
                            }
                            else
                            {
                                throw new Exception("计算班次错误");
                            }

                            monthStart += TimeSpan.FromDays(1);
                        }
                    }

                    if (Entity.Type == ShiftGroupType.两班倒)
                    {
                        WorkDate = info.WorkDate;
                        ShiftTag = info.ShiftTag;
                        {
                            var m = Math.Abs((DateTime.Today - info.WorkDate.Value.ToDateTime(TimeOnly.MinValue)).Days %
                                             2);
                            if (m == 0)
                            {
                                WorkDate = DateOnly.FromDateTime(DateTime.Today);
                            }
                            else if (m == 1)
                            {
                                WorkDate = DateOnly.FromDateTime(DateTime.Today);
                                ShiftTag = "休";
                            }
                            else
                            {
                                throw new Exception("计算班次错误");
                            }
                        }
                        var monthStart = new DateTime(DateTime.Now.Year, info.WorkDate.Value.Month, 1);
                        var monthDays = DateTime.DaysInMonth(DateTime.Now.Year, DateTime.Now.Month);
                        for (int i = 0; i < monthDays; i++)
                        {
                            var dayCount = (monthStart - info.WorkDate.Value.ToDateTime(TimeOnly.MinValue)).Days;
                            var mod = Math.Abs(dayCount % 2);
                            if (mod == 0)
                            {
                                SimpleSchedule.Add(DateOnly.FromDateTime(monthStart), "班");
                            }
                            else if (mod == 1)
                            {
                                SimpleSchedule.Add(DateOnly.FromDateTime(monthStart), "休");
                            }
                            else
                            {
                                throw new Exception("计算班次错误");
                            }

                            monthStart += TimeSpan.FromDays(1);
                        }
                    }

                    if (Entity.Type == ShiftGroupType.上一休二)
                    {
                        WorkDate = info.WorkDate;
                        ShiftTag = info.ShiftTag;

                        // 计算今天应该是什么班次
                        var m = Math.Abs((DateTime.Today - info.WorkDate.Value.ToDateTime(TimeOnly.MinValue)).Days % 3);
                        if (m == 0)
                        {
                            WorkDate = DateOnly.FromDateTime(DateTime.Today);
                            ShiftTag = "班";
                        }
                        else if (m == 1)
                        {
                            WorkDate = DateOnly.FromDateTime(DateTime.Today);
                            ShiftTag = "休1";
                        }
                        else if (m == 2)
                        {
                            WorkDate = DateOnly.FromDateTime(DateTime.Today);
                            ShiftTag = "休2";
                        }
                        else
                        {
                            throw new Exception("计算班次错误");
                        }

                        // 生成本月排班日历
                        var monthStart = new DateTime(DateTime.Now.Year, info.WorkDate.Value.Month, 1);
                        var monthDays = DateTime.DaysInMonth(DateTime.Now.Year, DateTime.Now.Month);

                        for (int i = 0; i < monthDays; i++)
                        {
                            var dayCount = (monthStart - info.WorkDate.Value.ToDateTime(TimeOnly.MinValue)).Days;
                            var mod = Math.Abs(dayCount % 3);

                            if (mod == 0)
                            {
                                SimpleSchedule.Add(DateOnly.FromDateTime(monthStart), "班");
                            }
                            else if (mod == 1)
                            {
                                SimpleSchedule.Add(DateOnly.FromDateTime(monthStart), "休1");
                            }
                            else if (mod == 2)
                            {
                                SimpleSchedule.Add(DateOnly.FromDateTime(monthStart), "休2");
                            }
                            else
                            {
                                throw new Exception("计算班次错误");
                            }

                            monthStart += TimeSpan.FromDays(1);
                        }
                    }
                }
            }
        }

        //1 2 3 4 5 6


        public override void Validate()
        {
            // 根据不同的排班类型，处理排班模式的存储
            if (Entity.Type == ShiftGroupType.行政班)
            {
                Entity.SchedulePattern = JsonSerializer.Serialize(WorkDays);
            }
            else if (Entity.Type == ShiftGroupType.三班倒 && WorkDate != null)
            {
                // 三班倒仅存储白班的工作日期，其他班次通过计算得出
                if (ShiftTag == "A")
                {
                    var info = new ShiftGroupDayInfo
                    {
                        WorkDate = WorkDate,
                        ShiftTag = "A"
                    };
                    Entity.SchedulePattern = JsonSerializer.Serialize(info);
                }
                else if (ShiftTag == "B")
                {
                    var info = new ShiftGroupDayInfo
                    {
                        WorkDate = WorkDate.Value.AddDays(2),
                        ShiftTag = "A"
                    };
                    Entity.SchedulePattern = JsonSerializer.Serialize(info);
                }
                else if (ShiftTag == "休")
                {
                    var info = new ShiftGroupDayInfo
                    {
                        WorkDate = WorkDate.Value.AddDays(1),
                        ShiftTag = "A"
                    };
                    Entity.SchedulePattern = JsonSerializer.Serialize(info);
                }
                else
                {
                    throw new Exception("请选择正确的班次");
                }
            }
            else if (Entity.Type == ShiftGroupType.两班倒 && WorkDate != null)
            {
                // 两班倒仅存储班的工作日期，休息日通过计算得出
                if (ShiftTag == "班")
                {
                    var info = new ShiftGroupDayInfo
                    {
                        WorkDate = WorkDate,
                        ShiftTag = "班"
                    };
                    Entity.SchedulePattern = JsonSerializer.Serialize(info);
                }
                else if (ShiftTag == "休")
                {
                    var info = new ShiftGroupDayInfo
                    {
                        WorkDate = WorkDate.Value.AddDays(1),
                        ShiftTag = "班"
                    };
                    Entity.SchedulePattern = JsonSerializer.Serialize(info);
                }
                else
                {
                    throw new Exception("请选择正确的班次");
                }
            }
            else if (Entity.Type == ShiftGroupType.上一休二 && WorkDate != null)
            {
                // 上一休二仅存储"班"的工作日期,其他班次通过计算得出
                if (ShiftTag == "班")
                {
                    var info = new ShiftGroupDayInfo
                    {
                        WorkDate = WorkDate,
                        ShiftTag = "班"
                    };
                    Entity.SchedulePattern = JsonSerializer.Serialize(info);
                }
                else if (ShiftTag == "休1")
                {
                    var info = new ShiftGroupDayInfo
                    {
                        WorkDate = WorkDate.Value.AddDays(-1),
                        ShiftTag = "班"
                    };
                    Entity.SchedulePattern = JsonSerializer.Serialize(info);
                }
                else if (ShiftTag == "休2")
                {
                    var info = new ShiftGroupDayInfo
                    {
                        WorkDate = WorkDate.Value.AddDays(-2),
                        ShiftTag = "班"
                    };
                    Entity.SchedulePattern = JsonSerializer.Serialize(info);
                }
                else
                {
                    throw new Exception("请选择正确的班次");
                }
            }

            else
            {
                MSD.AddModelError(" ", "排班类型或排班模式不能为空");
            }

            base.Validate();
        }

        public override async Task DoAddAsync()
        {
            // 校验班次不能为空
            if (SelectedShiftsIds == null || !SelectedShiftsIds.Any())
            {
                MSD.AddModelError("SelectedShiftsIds", "班次不能为空");
                return;
            }

            // 校验非行政班必须包含A标签
            if (Entity.Type != ShiftGroupType.行政班)
            {
                if (ShiftTagMapping == null || !ShiftTagMapping.Values.Contains(SysAttendanceShiftTag.A))
                {
                    MSD.AddModelError("ShiftTagMapping", "非行政班必须至少包含一个A标签的班次");
                    return;
                }
            }

            Entity.Shifts = new List<SysAttendanceShiftAndGroup>();
            if (SelectedShiftsIds != null)
            {
                foreach (var id in SelectedShiftsIds)
                {
                    SysAttendanceShiftAndGroup middle = new SysAttendanceShiftAndGroup
                    {
                        ShiftId = Guid.Parse(id),
                        // 如果映射表中有该班次的标签就使用,否则为null
                        Tag = ShiftTagMapping?.ContainsKey(id) == true ? ShiftTagMapping[id] : null
                    };
                    Entity.Shifts.Add(middle);
                }
            }

            Entity.ID = Uuid.NewDatabaseFriendly(Database.SqlServer);
            await base.DoAddAsync();
        }

        public override async Task DoEditAsync(bool updateAllFields = false)
        {
            // 校验班次不能为空
            if (SelectedShiftsIds == null || !SelectedShiftsIds.Any())
            {
                MSD.AddModelError("SelectedShiftsIds", "班次不能为空");
                return;
            }

            // 校验非行政班必须包含A标签
            if (Entity.Type != ShiftGroupType.行政班)
            {
                if (ShiftTagMapping == null || !ShiftTagMapping.Values.Contains(SysAttendanceShiftTag.A))
                {
                    MSD.AddModelError("ShiftTagMapping", "非行政班必须至少包含一个A标签的班次");
                    return;
                }
            }

            Entity.Shifts = new List<SysAttendanceShiftAndGroup>();
            if (SelectedShiftsIds != null)
            {
                foreach (var item in SelectedShiftsIds)
                {
                    SysAttendanceShiftAndGroup middle = new SysAttendanceShiftAndGroup
                    {
                        ShiftId = Guid.Parse(item),
                        // 如果映射表中有该班次的标签就使用,否则为null
                        Tag = ShiftTagMapping?.ContainsKey(item) == true ? ShiftTagMapping[item] : null
                    };
                    Entity.Shifts.Add(middle);
                }
            }

            await base.DoEditAsync(updateAllFields);
        }
    }
}